#include <Utils/Type.h>
#include "HalAlgDES.h"
#include "HalAlgGloBuff.h"
#include "string.h"
#include "../alg_pr/ALGDes_PR.h" 

#define DES_BLOCK_SIZE 	8
#define DES_KEY_LEN 	24
#define DES_IV_LEN		8


UINT32 HalAlgDES_Init(UINT8 Key[], UINT8 KLen, UINT8 IV[])
{
	UINT8 *l_ptr;
	
	if(Key != NULL)
	{		               
		l_ptr = (UINT8*)GetAlgKeyBuff();
		memcpy(l_ptr, Key, KLen);         
	}
	
	if(IV != NULL)
	{
		l_ptr =  (UINT8*)GetAlgIVBuff();
		memcpy(l_ptr, IV, DES_IV_LEN);
	}
	 
   	return RT_OK;
}


UINT32 HalAlgDES_Encrypt_Update(UINT32 Mode, UINT8 *pInBuf, UINT16 nSize, UINT8 *pOutBuf)
{
    UINT8 nRet;
    UINT8 l_mode;
    UINT8* l_iv_ptr, *l_key_ptr;

	if(pInBuf ==NULL)
	{
		return RT_FAIL;
	}
	
	if(nSize%DES_BLOCK_SIZE != 0)
	{
		return RT_FAIL;	
	}
	
	l_iv_ptr = (UINT8*)GetAlgIVBuff();
	l_key_ptr = (UINT8*)GetAlgKeyBuff();
	
	switch(Mode)
	{
		case HALALGDES1_MODE_ECB:
			l_mode = DES_ECB;
			l_iv_ptr = NULL;
			break;
		case HALALGDES1_MODE_CBC:
			l_mode = DES_CBC;			
			break;
		case HALALGDES3_MODE_ECB:
		    l_mode = DES3_ECB;
		    l_iv_ptr = NULL;
			break;
		case HALALGDES3_MODE_CBC:
			l_mode = DES3_CBC;
			break;
		case HALALGDES2_MODE_ECB:
		    l_mode = DES3_ECB;
        	memcpy(l_key_ptr + 16, l_key_ptr ,8);
		    l_iv_ptr = NULL;
			break;
		case HALALGDES2_MODE_CBC:
			l_mode = DES3_CBC;
        	memcpy(l_key_ptr + 16, l_key_ptr ,8);
			break;
		default :
			return RT_FAIL;
	} 

    nRet = ALGDes_PR_Run(DES_ENCRYPT, l_mode, pInBuf, pOutBuf, nSize, l_key_ptr, l_iv_ptr);
   
	return nRet;

}
UINT32 HalAlgDES_Decrypt_Update(UINT32 Mode, UINT8 *pInBuf, UINT16 nSize, UINT8* pOutBuf)
{
    UINT8 nRet ;
    UINT8 l_mode;
    UINT8* l_iv_ptr, *l_key_ptr;
    
	if(pInBuf ==NULL)
	{
		return RT_FAIL;
	}
	
	if(nSize%DES_BLOCK_SIZE != 0)
	{
		return RT_FAIL;	
	}
	
	l_iv_ptr = (UINT8*)GetAlgIVBuff();
	l_key_ptr = (UINT8*)GetAlgKeyBuff();
	
	switch(Mode)
	{
		case HALALGDES1_MODE_ECB:
			l_mode = DES_ECB;
			l_iv_ptr = NULL;
			break;
		case HALALGDES1_MODE_CBC:
			l_mode = DES_CBC;			
			break;
		case HALALGDES3_MODE_ECB:
		    l_mode = DES3_ECB;
		    l_iv_ptr = NULL;
			break;
		case HALALGDES3_MODE_CBC:
			l_mode = DES3_CBC;
			break;
		case HALALGDES2_MODE_ECB:
		    l_mode = DES3_ECB;
			memcpy(l_key_ptr + 16, l_key_ptr ,8);
		    l_iv_ptr = NULL;
			break;
		case HALALGDES2_MODE_CBC:
			memcpy(l_key_ptr + 16, l_key_ptr ,8);
			l_mode = DES3_CBC;
			break;
		default :
			return RT_FAIL;
	} 

    nRet = ALGDes_PR_Run(DES_DECRYPT, l_mode, pInBuf, pOutBuf, nSize, l_key_ptr, l_iv_ptr);
   
	return nRet;
}

UINT32 HalAlgDES_Final(void)
{
	UINT8 *l_ptr;
	
	l_ptr = (UINT8*)GetAlgIVBuff();
	memset(l_ptr, 0, DES_IV_LEN);
	l_ptr = (UINT8*)GetAlgKeyBuff();
	memset(l_ptr, 0, DES_KEY_LEN);
	
	return RT_OK;
}
